package Model;

import java.util.ArrayList;
import java.util.ListIterator;

/**
 * Classe permettant de gérer les dames, elle hérite de la classe Pièce
 * @see Piece
 * @author El Meknassi Hamza (10806466) - Migeon Cyril (11007322)
 */
public class Dame extends Piece{

    /**
     * Constructeur d'une dame
     * @param couleur couleur permettant d'identifier à quelle joueur appartient la dame
     * @param x coordonnée x de la dame sur le plateau
     * @param y coordonnée y de la dame sur le plateau
     * @param damier damier pour que l'on puisse y placer la dame
     */
    public Dame(char couleur, int x, int y, Damier damier)
    {
        super(couleur, x, y, damier);
    }

    /**
     * Fonction permettant de vérifier si un déplacement simple (sans prise) est possible ou pas
     * @param caseDepart Case de départ
     * @param caseCible Case cible
     * @param couleurDame Couleur de la dame qu'on essaye de bouger
     * @param joueur On donne le joueur en paramètre pour pouvoir vérifier qu'il a bien le droit de bouger la dame
     * @return <ul><li> Vrai si le déplacement est possible</li><li>Faux sinon</li></ul>
     */
    public boolean verifierDeplacementSimple(Case caseDepart, Case caseCible, char couleurDame, Joueur joueur){
        boolean booleen = true;
        //Coordonnées de la case cible
        int xCaseCible = caseCible.getPosition().getX();
        int yCaseCible = caseCible.getPosition().getY();
        //Coordonnées de la case de départ
        int x = caseDepart.getPosition().getX();
        int y = caseDepart.getPosition().getY();

        //On vérifie si le joueur a le droit de bouger ce pion
        if(!verifierCouleur(joueur.getCouleur(), this.getCouleur()))
            return false;

        //On vérifie que la case cible n'est pas occupée
        if(!verifierEtat(caseCible))
            return false;

        //On vérifie que le déplacement se fait en diagonale (peu importe le sens)
        if((xCaseCible != x+1 && xCaseCible != x-1) || (yCaseCible != y+1 && yCaseCible != y-1))
            booleen = false;

        return booleen;
    }
    /**
     * Fonction permettant de vérifier si la dame peut faire des prises
     * @param dame Pièce que l'on souhaite tester
     * @param piecesJouables Ensemble des pièces pouvant bouger
     * @return <ul><li> Vrai si la pièce est dans la liste</li><li>Faux sinon</li></ul>
     */
    public boolean verifierPieceDansPiecesJouables(Dame dame, ArrayList<Piece> piecesJouables){
        boolean booleen = false;
        ListIterator<Piece> itr = piecesJouables.listIterator();
        while(itr.hasNext())
        {
            if(dame == itr.next())
            {
                booleen = true;
                break;
            }
        }
        return booleen;
    }

    /**
     * Fonction permettant de vérifier si on peut faire une prise multiple après une prise simple
     * @param caseCible Case ou situe la pièce après la prise simple
     * @param joueur Paramètre nécessaire pour la fonction setPiecesJouables que l'on appelle dans cette fonction
     * @return <ul><li>Vrai si une autre prise est possible</li><li>Faux sinon</li></ul>
     */
    private boolean verifierNouvellePrise(Case caseCible, Joueur joueur) {
        //On oublie les anciennes cases proposées
        this.getDamier().viderCasesProposees();
        //On récupère la liste des pièces jouables
        this.getDamier().setPiecesJouables(caseCible, joueur);
        if (this.getDamier().getPiecesJouables().isEmpty())
            return false;
        else return true;
    }

    /**
     * Fonction permettant de gérer le déplacement des dames ainsi que les prises -> fonction à compléter
     * @param caseDepart Case de départ
     * @param caseCible Case sur laquelle on souhaite se déplacer
     * @param joueur Joueur effectuant l'opération
     * @param piecesJouables Liste des pièces jouables (pouvant faire une prise)
     * @return <ul><li>0 si le déplacement est impossible/li><li>1 si un déplacement ou prise
                      simple est possible</li><li>2 si une prise est encore possible après la prise effectuée</li> </ul>
     */
    public int deplacer(Case caseDepart, Case caseCible, Joueur joueur, ArrayList<Piece> piecesJouables){
        //On récupère le nombre de pièces pouvant faire une prise
        int nombrePiecesJouables = piecesJouables.size();

        //On peut faire un déplacement simple si la case cible le permet et si aucune dame ne peut faire une prise
        if(verifierDeplacementSimple(caseDepart, caseCible, this.getCouleur(), joueur) && nombrePiecesJouables == 0)
        {
            if(!verifierPieceDansPiecesJouables(this, piecesJouables) && nombrePiecesJouables != 0)
            {
                System.out.println("Vous avez la possibité d'effetuer une prise avec un autre pion !");
                return 0;
            }
            //Si on arrive ici alors toutes les verifications ont retournées true et on peut procéder au déplacement
            //On vide la case de départ
            caseDepart.setPiece(null);
            caseDepart.setEtat(0);
            //On occupe la case cible et on met à jour la position
            caseCible.setPiece(this);
            caseCible.setEtat(1);
            this.setPosition(caseCible.getPosition());
        }
        //S'il ne s'agit pas d'un simple déplacement, on teste s'il s'agit d'une prise
        else if(verifierDeplacementManger(caseDepart, caseCible, this.getCouleur(), joueur))
        {
            //Si on arrive ici alors toutes les verifications ont retournées true sauf le deplacement simple
            //et on peut procéder au déplacement pour manger une pièce adverse

            //On calcule les coordonnées de la case où se situe la pièce à manger
            int xCaseInter = (caseDepart.getPosition().getX() + caseCible.getPosition().getX()) / 2;
            int yCaseInter = (caseDepart.getPosition().getY() + caseCible.getPosition().getY()) / 2;
            Case caseInter = this.getDamier().getCase(xCaseInter, yCaseInter);

            //On vide la case de départ et la case intermédiaire
            caseDepart.setPiece(null);
            caseDepart.setEtat(0);
            caseInter.setPiece(null);
            caseInter.setEtat(0);
            //On occupe la case cible tout en mettant à jour la position
            caseCible.setPiece(this);
            caseCible.setEtat(1);
            this.setPosition(caseCible.getPosition());

            //On vérifie si le joueur peut effectuer une nouvelle prise avec la même pièce
            if (verifierNouvellePrise(caseCible, joueur))
                return 2;
        }
        else
        {
            System.out.println("Impossible d'effectuer ce déplacement");
            return 0;
        }

        return 1;
    }

    /**
     * Fonction de permettant de vérifier si une prise est possible
      * @param caseDepart Case de départ
     * @param caseCible Case sur laquelle on souhaite se déplacer
     * @param couleurPion Couleur du pion que l'on souhaite déplacer
     * @param joueur Joueur effectuant l'opération
     * @return <ul><li>Vrai si la prise est possible</li><li>Faux sinon</li></ul>
     */
    public boolean verifierDeplacementManger(Case caseDepart, Case caseCible, char couleurPion, Joueur joueur){
        boolean booleen = true;
        int xCaseCible = caseCible.getPosition().getX();
        int yCaseCible = caseCible.getPosition().getY();
        int x = caseDepart.getPosition().getX();
        int y = caseDepart.getPosition().getY();

        if(!verifierEtat(caseCible))
            return false;

        if(!verifierCouleur(joueur.getCouleur(), this.getCouleur()))
            return false;

        if((xCaseCible != x+2 && xCaseCible != x-2) || (yCaseCible != y+2 && yCaseCible != y-2))
            booleen = false;
        

        if(booleen)
        {
            //On calcule les coordonnées de la case intermédiaire
            int xCaseInter = (x + xCaseCible) / 2;
            int yCaseInter = (y + yCaseCible) / 2;
            //On teste l'etat et la couleur de la case intermédiaire
            if(verifierEtat(this.getDamier().getCase(xCaseInter, yCaseInter)))
                booleen = false;
            else
                if(verifierCouleur(joueur.getCouleur(), this.getDamier().getCase(xCaseInter, yCaseInter).getPiece().getCouleur()))
                    return false;
        }
        return booleen;
    }

    /**
     * Fonction permettant de voir si le joueur peut effectuer une prise
     * @param joueur
     * @return <ul><li>Vrai si une prise est possible</li><li>Faux sinon</li></ul>
     */
    @Override
     public boolean peutManger(Joueur joueur){
         Case[] caseCibles = new Case[4];
         boolean tableauBooleen[] = {true, true, true, true};

         int x = this.getPosition().getX();
         int y = this.getPosition().getY();

         Case caseDepart = this.getDamier().getCase(x, y);

         if(x+2 < 10 && y+2 < 10)
             caseCibles[0] = this.getDamier().getCase(x+2, y+2);
         else tableauBooleen[0]= false;

         if(x-2 > -1 && y+2 < 10)
             caseCibles[1] = this.getDamier().getCase(x-2, y+2);
         else tableauBooleen[1]= false;

         if(x+2 < 10 && y-2 > -1)
             caseCibles[2] = this.getDamier().getCase(x+2, y-2);
         else tableauBooleen[2]= false;

         if(x-2 > -1 && y-2 > -1)
             caseCibles[3] = this.getDamier().getCase(x-2, y-2);
         else tableauBooleen[3]= false;

         for(int i=0; i<4; i++)
         {
             if(caseCibles[i] != null)
             {
                 if(!verifierDeplacementManger(caseDepart, caseCibles[i], this.getCouleur(), joueur))
                     tableauBooleen[i] = false;
             }
         }
         return (tableauBooleen[0] || tableauBooleen[1] || tableauBooleen[2] || tableauBooleen[3]);
     }

}
